package com.jintian.smart.base.expression.expr.function;

import com.jintian.smart.base.api.system.provider.IEmployeeProvider;
import com.jintian.smart.base.expression.fn.HasRoleFunction;
import com.jintian.smart.kernel.common.context.ContextHolder;
import com.jintian.smart.kernel.common.util.StringUtil;
import com.jintian.smart.kernel.core.annotation.expr.ExprFn;
import com.jintian.smart.kernel.redis.core.RedisService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.PatternMatchUtils;

import java.util.List;

@ExprFn(code = "")
public class RequestContextFn {
    /**
     * 所有权限标识
     */
    private static final String ALL_PERMISSION = "*:*:*";

    private static RequestContextFn _INSTANCE;
    @DubboReference(check = false)
    private IEmployeeProvider employeeProvider;
    @Autowired
    private RedisService redisService;
    @Autowired
    private HasRoleFunction hasRoleFunction;

    public RequestContextFn() {
        _INSTANCE = this;
    }

    private Object _userInfo(Object... paras) {
        String prop = (String) paras[0];
        if (StringUtil.isEmpty(ContextHolder.getUserId())) {
            Object defaultValue = paras.length > 1 ? paras[1] : null;
            return defaultValue;
        }
        if ("name".equals(prop)) {
            return ContextHolder.getName();
        } else if ("id".equals(prop)) {
            return ContextHolder.getUserId();
        }
        // todo 地区支持尚未实现
//        else if ("areaCode".equals(prop)) {
//            return this.employeeProvider.getById(ContextHolder.getUserId()).getAreaCode();
//        }
        else {
            throw new IllegalArgumentException("userInfo函数不支持" + prop);
        }
    }

    private boolean _hasPermission(Object... paras) {
        if (StringUtil.isEmpty(ContextHolder.getUserId())) {
            return false;
        }
        String permission = (String) paras[0];
        @SuppressWarnings("unchecked")
        List<String> authorities = (List<String>) this.redisService.getObject("mate:permission:" + ContextHolder.getName(), List.class);
        if (authorities == null) {
            return false;
        }
        return authorities.stream().filter(StringUtil::isNotEmpty).anyMatch(x -> ALL_PERMISSION.contains(x) || PatternMatchUtils.simpleMatch(permission, x));
    }

    private boolean _hasRole(Object... paras) {
        String userId = ContextHolder.getUserId();
        if (StringUtil.isEmpty(userId)) {
            return false;
        }
        String roleCode = (String) paras[0];
        return Boolean.TRUE.equals(this.hasRoleFunction.call(new Object[]{userId, roleCode}, null));
    }

    @ExprFn(code = "userInfo")
    public static Object userInfo(Object... paras) {
        return _INSTANCE._userInfo(paras);
    }

    @ExprFn(code = "userId")
    public static Object userId(Object... paras) {
        return ContextHolder.getUserIdLong();
    }

    @ExprFn(code = "userName")
    public static Object userName(Object... paras) {
        return ContextHolder.getUserName();
    }

    @ExprFn(code = "hasPermission")
    public static boolean hasPermission(Object... paras) {
        return _INSTANCE._hasPermission(paras);
    }

    @ExprFn(code = "hasRole")
    public static boolean hasRole(Object... paras) {
        return _INSTANCE._hasRole(paras);
    }

}
